﻿/******************************************************************************
 * 
 * Announce: CSharpKit, Basic algorithms, components and definitions.
 *           Copyright (C) ShenYongchen.
 *           All rights reserved.
 *   Author: 申永辰.郑州 (shenyczz@163.com)
 *  WebSite: http://github.com/shenyczz/CSharpKit
 *
 * THIS CODE IS LICENSED UNDER THE MIT LICENSE (MIT).
 * THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
 * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
 * IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
 * PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
 * 
******************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;

namespace CSharpKit.SVM
{
    /// <summary>
    /// 参数
    /// </summary>
    [Serializable]
    public class SvmParameter : IEquatable<SvmParameter>
    {
        #region Constructors

        public SvmParameter()
        {
            SvmType = SvmType.C_SVC;
            KernelType = KernelType.RBF;
            Degree = 3;
            Gamma = 1; // 1 / num_of_features ： 1 / k
            Coef0 = 0;

            // for train
            C = 1;
            Nu = 0.5;
            P = 0.1;
            CacheSize = 100;
            Eps = 0.001;
            Shrinking = true;
            Probability = false;

            Weights = new Dictionary<int, double>();

        }


        internal SvmParameter(SvmParameter rhs)
        {
            SvmType = rhs.SvmType;
            KernelType = rhs.KernelType;
            Degree = rhs.Degree;
            Gamma = rhs.Gamma;
            Coef0 = rhs.Coef0;

            C = rhs.C;
            Nu = rhs.Nu;
            P = rhs.P;
            CacheSize = rhs.CacheSize;
            Eps = rhs.Eps;
            Shrinking = rhs.Shrinking;
            Probability = rhs.Probability;

            Weights = new Dictionary<int, double>();
        }

        #endregion

        #region Properties

        /// <summary>
        /// 支持向量机类型: C_SVC, NU_SVC, ONE_CLASS, EPS_SVR, NU_SVR, 默认是"C_SVC"<br/>
        /// [C_SVC] n类分类(n >= 2), 允许不完全分离的类与惩罚乘数C的离群点<br/>
        /// [NU_SVC] 具有可能不完全分离的n类分类. 参数 Nu 在(0,1)<br/> 
        /// [ONE_CLASS] 分布估计(1分类). 所有的训练数据都来自同一个类，SVM构建了一个边界，将类与特征空间的其余部分分隔开<br/>
        /// [EPS_SVR] 向量回归， 特征向量与训练集和拟合超平面之间的距离必须小于P. 对于异常值，使用惩罚乘数C。<br/>
        /// [NU_SVR] nu-Support 向量回归, 用Nu代替p <br/>
        /// </summary>
        public SvmType SvmType { get; set; }

        /// <summary>
        /// 核函数类型: LINEAR, POLY, RBF, SIGMOID, 默认是"RBF"<br/>
        /// [LINEAR] 线性函数，在原始特征空间中做线性判别或回归，F = u'*v<br/>
        /// [POLY] 多项式函数，F = (gamma*u'*v + coef0)^degree<br/>
        /// [RBF] 径向基函数, F = exp(-gamma*||u-v||^2)<br/>
        /// [SIGMOID] S型函数, F = tanh(gamma*u'*v + coef0)<br/>
        /// </summary>
        public KernelType KernelType { get; set; }

        /// <summary>
        /// 名称：核函数的 degree 参数<br/>
        /// 用途：决定了多项式的最高次幂, Default=3<br/>
        /// 备注：适用于核类型 POLY<br/>
        /// </summary>
        public int Degree { get; set; }
        /// <summary>
        /// 核函数的 gamma 参数,
        /// 默认是gamma = 1 / n_features (KernelType: POLY / RBF / SIGMOID).
        /// </summary>
        public double Gamma { get; set; }
        /// <summary>
        /// Zeroeth coefficient in kernel function (default 0)
        /// 核函数的 coef0 参数, 核函数中的独立项, default = 0 (KernelType: POLY / SIGMOID).
        /// </summary>
        public double Coef0 { get; set; }


        //
        // these are for training only following
        //

        /// <summary>
        /// 制定训练所需要的内存(以MB为单位), default = 100
        /// </summary>
        public Double CacheSize { get; set; }
        /// <summary>
        /// Tolerance of termination criterion (default 0.001)
        /// svm迭代训练过程的精度, default = 0.001
        /// </summary>
        public double Eps { get; set; }
        /// <summary>
        /// 目标函数的惩罚系数C，用来平衡分类间隔margin和错分样本的，default C = 1.0
        ///  (KernelType: C_SVC / EPS_SVR / NU_SVR)<br/>
        /// </summary>
        public double C { get; set; }

        /// <summary>
        /// Contains custom weights for class labels.  Default weight value is 1<br/>
        /// label: int<br/>
        /// weight: double<br/>
        /// </summary>
        public Dictionary<int, double> Weights { get; private set; }


        /// <summary>
        /// The parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
        /// Parameter nu of a SVM optimization problem (NU_SVC / ONE_CLASS / NU_SVR).
        /// </summary>
        public double Nu { get; set; }
        /// <summary>
        /// The epsilon in loss function of EPS-SVR (default 0.1)
        /// </summary>
        public double P { get; set; }
        /// <summary>
        /// 是否进行启发式, (default true)
        /// </summary>
        public bool Shrinking { get; set; }
        /// <summary>
        /// 训练SVC或SVR模型是否进行概率估计, (default false)
        /// </summary>
        public bool Probability { get; set; }

        #endregion


        public SvmParameter Clone()
        {
            return new SvmParameter(this);
        }


        #region Override functions

        public bool Equals(SvmParameter other)
        {
            return true
                && other != null
                && SvmType == other.SvmType
                && KernelType == other.KernelType
                && Degree == other.Degree
                && Gamma == other.Gamma
                && Coef0 == other.Coef0
                && CacheSize == other.CacheSize
                && Eps == other.Eps
                && C == other.C
                && Nu == other.Nu
                && P == other.P
                && Shrinking == other.Shrinking
                && Probability == other.Probability
                && other.Weights.ToArray().IsEqual(Weights.ToArray())
                ;
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as SvmParameter);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode()
                ^ SvmType.GetHashCode()
                ^ KernelType.GetHashCode()
                ^ Degree.GetHashCode()
                ^ Gamma.GetHashCode()
                ^ Coef0.GetHashCode()
                ^ CacheSize.GetHashCode()
                ^ Eps.GetHashCode()
                ^ C.GetHashCode()
                ^ Nu.GetHashCode()
                ^ P.GetHashCode()
                ^ Shrinking.GetHashCode()
                ^ Probability.GetHashCode()
                ^ Weights.ToArray().ComputeHashcode()
               ;
        }

        public override string ToString()
        {
            return base.ToString();
        }

        #endregion

        //}}@@@
    }



}
